
#ifndef XDNS_SERVER_STATE_IMPL_H
#define XDNS_SERVER_STATE_IMPL_H

#include "xdns-server-state.h"
#include <map>

class XdnsData;

class XdnsServerStateImpl : public XdnsServerState
{
public:
    friend class XdnsServerState;

    /* See xdns-server-state.h for description. */
    virtual XdnsError SendQuery(long queryId,
                                const XdnsQuery& query);
    virtual void CancelQuery(long queryId);
    virtual XdnsError GetProcessingFds(int* nfds,
                                       fd_set* readfds,
                                       fd_set* writefds);
    virtual XdnsError Process(fd_set* readfds,
                              fd_set* writefds);

private:
    XdnsServerStateImpl(unsigned short port,
                        const struct in_addr* address);
    virtual ~XdnsServerStateImpl();

    XdnsError GetValidRequestId(unsigned short& requestId,
                                std::map<unsigned short, long>::iterator& iter);
    unsigned short NextRequestId();
    XdnsError OpenUdpSocket();
    XdnsError SendDataViaUdp(const XdnsData& data,
                             size_t startOffset);
    XdnsError RecvDataViaUdp(fd_set* readfds);
    XdnsError AddToPendingQueue(long queryId,
                                const XdnsQuery& query);
    XdnsError ProcessReply(const XdnsData& data,
                           size_t startOffset);

    unsigned short m_nextRequestId;
    int m_udpSocket;

    /* The relationship between the request IDs of DNS protocol and
       the query IDs.
    */
    std::map<unsigned short, long> m_relatedIds;

    /* Save the pending queries if no valid request IDs could be
       used to send. They are activated to send when a query is
       responded and a request ID is freed.
    */
    std::map<long, XdnsData*> m_pendingQueries;
};

#endif  // XDNS_SERVER_STATE_IMPL_H

